#ifndef _PARTICLE_H
#define _PARTICLE_H

#include "Vector3.h"



/* The particle class represents a particle of mass that can move around in 3D space*/
class Particle
{
public:
	bool movable; // can the particle move or not ? used to pin parts of the cloth

	float mass; // the mass of the particle (is always 1 in this example)
	float inverseMass;	// the inverse mass of the particle

	Vector3 oldVelocity; // for velocity term
	Vector3 velocity;
	Vector3 newVelocity;	// temporary item

	Vector3 position; // the current position of the particle in 3D space
	Vector3 oldPosition; // the position of the particle in the previous time step, used as part of the verlet numerical integration scheme
	Vector3 newPosition; // temporary item
	Vector3 acceleration; // a vector representing the current acceleration of the particle
	Vector3 accumulated_normal; // an accumulated normal (i.e. non normalized), used for OpenGL soft shading

public:
	Particle(Vector3 pos) : position(pos), oldPosition(pos), newPosition(pos) ,acceleration(Vector3(0,0,0)), velocity(Vector3(0,0,0)), oldVelocity(velocity),newVelocity(velocity) , mass(1), inverseMass(1), movable(true), accumulated_normal(Vector3(0,0,0)){}
	Particle(){}

	/* Set inverse mass of the particle. */
	void setInverseMass(float aInverseMass){
		inverseMass = aInverseMass;
	}

	void addForce(const Vector3& f)
	{
		acceleration += f * inverseMass;
	}

	void setVelocity(Vector3& aVelocity){
		velocity = aVelocity;
	}

	Vector3& getVelocity(){
		return velocity;
	}

	///* This is one of the important methods, where the time is progressed a single step size (TIME_STEPSIZE)
	//   The method is called by Cloth.time_step()
	//   Given the equation "force = mass * acceleration" the next position is found through verlet integration*/
//#define DAMPING 0.01 // how much to damp the cloth simulation each frame
//#define TIME_STEPSIZE2 0.1
//	void timeStep()
//	{
//		if(movable)
//		{
//			Vector3 temp = position;
//			position = position + (position-oldPosition)*(1.0-DAMPING) + acceleration*TIME_STEPSIZE2;
//			oldPosition = temp;
//			acceleration = Vector3(0,0,0); // acceleration is reset since it HAS been translated into a change in position (and implicitely into velocity)	
//		}
//	}

	Vector3& getOldPos() {return oldPosition;}

	Vector3& getPos() {return position;}
	void setPos(Vector3& aPos) {
		position = aPos;
	}

	void resetAcceleration() {acceleration = Vector3(0,0,0);}

	void offsetPos(const Vector3& v) { if(movable) position += v;}

	void makeUnmovable() {
		movable = false;
		// infinite mass means unmovable
		inverseMass = 0;
		velocity = Vector3(0,0,0);
		acceleration = Vector3(0,0,0);
		oldPosition = position;
	}

	void addToNormal(Vector3& normal)
	{
		accumulated_normal += normal.normalisedCopy();
	}

	Vector3& getNormal() { return accumulated_normal;} // notice, the normal is not unit length

	void resetNormal() {accumulated_normal = Vector3(0,0,0);}

};

#endif